import metadata
import sys
import musicbrainz2.disc as mbdisc
import musicbrainz2.webservice as mbws
import traceback
from musicbrainz2.model import Release as releasetype
from musicbrainz2.utils import extractUuid
from util import minimalistName


    
def FreeLookup(string):
    print("Looking up: %s" % string)
    service = mbws.WebService()
    query = mbws.Query(service)
    #This is the old syntax - matches must be EXACT.
    #filter = mbws.ReleaseFilter(title = album, artistName = artist)
    #This is the newer syntax
    filter = mbws.ReleaseFilter(query=string)
    results = query.getReleases(filter)
    ans = []
    scores = []
    for result in results:
        r = result.getRelease()
        #inc = mbws.ReleaseIncludes(artist=True, tracks=True, releaseEvents=True, discs=True)
        #release = query.getReleaseById(r.getId(), inc)
        ans = ans + [r]
        scores = scores + [result.getScore()]
        print("%d: %s - %s (%d)" % (result.getScore(), r.getArtist().getName(), r.getTitle(), r.getTracksCount(),))
        #print result
    
    return results

def Lookup(artist, album):
    
    
    album = minimalistName(album)
    artist = minimalistName(artist)
    
    #print("Looking up: %s, %s" % (artist, album))
    
    #return( FreeLookup(artist+"~ " + album + "~"))
    #bizzarely, artist tags make a difference, title tags don't.
    #return( FreeLookup("artist:\""+artist+"\" \"" + album + "\""))
    return( FreeLookup("artist:\""+artist+"\" " + album ))    
    

class MusicBrainException(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)    

class MusicBrain:
    def __init__(self):
        self.service = mbws.WebService()
        self.query = mbws.Query(self.service)
    

class MBalbum(metadata.AlbumMetadata):    
    def __init__(self, perfectMatch = True):        
        #self.discId = discId
        
        self.service = mbws.WebService()
        self.query = mbws.Query(self.service)
        self.perfectMatch = perfectMatch
        
    def LoadFromDisc(self, discid):
        self.discId = discid
        try:
            filter = mbws.ReleaseFilter(discId = self.discId)
            results = self.query.getReleases(filter)
        except mbws.WebServiceError, e:
            print "Error:", e
            raise MusicBrainException, e
        
        if len(results)==0:
            print "Unknown disc id (has it been added to the databse?)"
            raise MusicBrainException, "unknown disc"
        
        if len(results) > 1:
            print "Multiple results found"
        maxscore = -1
        for result in results:
            if( result.score > maxscore ):
                release = result.release
                maxscore = result.score
        
        #print "Assuming %s/%s [score: %d]" % (release.artist.name, release.title, maxscore)
        else:
            maxscore = results[0].score
            release = results[0].release
        
        print "Music brainz data: %s/%s [score: %d]" % (release.artist.name, release.title, maxscore)
        if( self.perfectMatch):
            if( maxscore != 100):
                print "Imperfect match."
                raise MusicBrainException, "imperfect match"
        
        self.LoadFromReleaseId(release.getId())

    def LoadFromReleaseId(self, releaseId):
        
        #now we need to load the remaining data.
        try:
            inc = mbws.ReleaseIncludes(artist=True, tracks=True, releaseEvents=True, discs=True, releaseRelations=True, urlRelations=True)
            self.release = self.query.getReleaseById(releaseId, inc)
        except mbws.WebServiceError, e:
            traceback.print_exc()
            print "Error:", e
            raise MusicBrainException, e
        
        
        self.tracks = {}
        j = self.release.getTracksOffset()
        if ( j == None):
            j = 0
        for t in self.release.getTracks():
            track = t
            #track = self.query.getTrackById( t.getId() )
            #print "Track :", t
            #musicbrainz tracks are 0 offsetted. Most people start at track 1
            j=j+1
            self.tracks[ j ] = MBtrack(self, track, j) 
        
        #finally no disc id
        self.discId = None
        print "Loaded data ok [%s]" % (releaseId)
        return True

    def getTracks(self):
        return self.tracks

    def getAlbumName(self):
        return self.release.title
    
    def getTotalTracks(self):
        return "%d" % len(self.release.tracks)

    def getDiscId(self):
        return self.discId
    
    def getAsin(self):
        return self.release.getAsin()
    
    def getDiscogs(self):
        rs = self.release.getRelations(relationType="http://musicbrainz.org/ns/rel-1.0#Discogs")
        disco = None
        for r in rs:
            #print "relation %s found." % r.getType()
            disco = r.getTargetId()
        
        #print "Discogs: %s"%disco
        return  disco
    
    def getAlbumArtist(self):
        return self.release.artist.name

    def getReleaseType(self):
        ts = self.release.getTypes()
        for t in ts:
            if (~(t in ( releasetype.TYPE_OFFICIAL, 
                      releasetype.TYPE_PROMOTION, 
                      releasetype.TYPE_BOOTLEG, 
                      releasetype.TYPE_PSEUDO_RELEASE ))):
                #this hack is to extract the string from the constant
                return t.partition('#')[2].lower()

    def getAlbumId(self):
        return extractUuid(self.release.getId())

    def getReleaseStatus(self):
        ts = self.release.getTypes()
        for t in ts:
            if t in ( releasetype.TYPE_OFFICIAL, 
                      releasetype.TYPE_PROMOTION, 
                      releasetype.TYPE_BOOTLEG, 
                      releasetype.TYPE_PSEUDO_RELEASE ):
                #this hack is to extract the string from the constant
                return t.partition('#')[2].lower()

    def getAlbumArtistId(self):
        return extractUuid(self.release.artist.getId())

    def getDate(self):
        #print "Date is %r" % self.release.getEarliestReleaseDate()
        return self.release.getEarliestReleaseDate()

    def getCompilation(self):
        #does this album have > 1 artist? if so it's a compilation
        return "%d" % (self.release.isSingleArtistRelease() == False )
    
class MBtrack(metadata.TrackMetadata):
    
    def __init__(self, album, track, tracknumber):
        #track is musicbrainz2 track model
        metadata.TrackMetadata.__init__( self, album )
        self.track = track
        self.tracknumber = tracknumber
        
    def getArtist(self):
        artist = self.track.getArtist();
        if (artist == None):
            return extractUuid(self.album.release.artist.getUniqueName())
        #else multi artist album...
        
        return extractUuid(artist.getName() )
        
    def getArtistId(self):
        artist = self.track.getArtist()
        if (artist != None):
            #This can happen if the CD has 1 track from a 'guest' artist.
            #however seems mean to file it under "Various Artists" in this case.        
            return extractUuid(artist.getId() )
        return extractUuid(self.album.release.artist.getId())
        
    def getTrackId(self):
        return extractUuid(self.track.getId())
        
    def getTitle(self):
        return self.track.getTitle()
        
    def getTrackNumber(self):
        return "%d" % self.tracknumber
        

